package com.example.myapplication.ui.download

import android.util.Log
import androidx.lifecycle.*
import com.example.myapplication.App
import com.example.myapplication.databaseThreadPool
import com.example.myapplication.ui.FileBean.Companion.STATE_DEFAULT_FLAG
import com.example.myapplication.ui.FileBean.Companion.STATE_NET_FLAG
import com.example.myapplication.utils.FileDownloadUtils
import okhttp3.Call
import okhttp3.Response
import java.io.IOException
import java.util.*
import java.util.concurrent.Executors
import java.util.concurrent.atomic.AtomicInteger

class FileDownloadViewModel : ViewModel(), DefaultLifecycleObserver {

    private val dao: FileDownloadDao = App.instance.database.fileDownloadDao()

    private val netThreadPool = Executors.newFixedThreadPool(3)

    private val map = mutableMapOf<String, Call>()

    private var timer: Timer = Timer()

    private val timerReDownloadTask = object : TimerTask() {
        override fun run() {
            if (currTask() >= 2) return
            dao.getOtherNotDownloadTask()?.also {
                Log.e("FileUploadViewModel", "Timer > ${it.name}")
                retry(it)
            }
        }
    }

    init {
        timer.schedule(timerReDownloadTask, 0, 2000)
    }
    /**
     * 插入新任务
     */
    fun insert(word: FileDownloadBean) {
        Log.e("FileDownloadViewModel", "insert 1")
        if (!word.enabled) {
            // TODO 正式删除
            databaseThreadPool.execute {
                dao.insert(word)
            }
        }
        if (word.enabled && !word.deleted) {
            // TODO download
            Log.e("FileDownloadViewModel", "insert 2")
            databaseThreadPool.execute {
                Log.e("FileDownloadViewModel", "insert 3")
                dao.insert(word)
                startDownloadFile(word)
            }
        }
    }
    /**
     * 未完成任务重试
     */
    fun retry(it: FileDownloadBean) {
        upload(it.apply {
            this.downloadSpeed = 0
            this.downloadState = FileDownloadBean.DOWNLOAD_READY
            this.state = "${STATE_DEFAULT_FLAG}正在等待..."
        })
        startDownloadFile(it)
    }
    /**
     * 更新任务
     */
    fun upload(word: FileDownloadBean) {
        if (word.enabled && !word.deleted) {
            upload(
                word.uuid,
                word.length,
                word.downloadSize,
                word.downloadState,
                word.downloadSpeed,
                word.state
            )
        }
    }
    /**
     * 更新任务
     */
    fun upload(
        uuid: String,
        length: Long,
        downloadSize: Long,
        downloadState: Byte,
        downloadSpeed: Long,
        state: String
    ) {
        databaseThreadPool.execute {
            dao.update(
                uuid,
                length,
                downloadSize,
                downloadState,
                downloadSpeed,
                state
            )
        }
    }

    /**
     * 移除所有任务
     */
    fun deleteAll() {
        databaseThreadPool.execute {
            dao.deleteFinishAll()
        }
    }
    /**
     * 移除指定UUID任务
     */
    fun deleteByUUID(bean: FileDownloadBean) {
        databaseThreadPool.execute {
            dao.deleteByUUID(bean.uuid)
        }
        map.remove(bean.uuid)?.cancel()
    }

    /**
     * 移除所有运行任务
     */
    fun deleteRunningTask() {
        databaseThreadPool.execute {
            dao.deleteRunningAll()
        }
    }
    /**
     * 更新所有异常任务
     */
    fun updateErrorTask() {
        databaseThreadPool.execute {
            dao.updateErrorAll()
        }
    }
    /**
     * 移除所有异常任务
     */
    fun deleteErrorTask() {
        databaseThreadPool.execute {
            dao.deleteErrorAll()
        }
    }

    fun getAllFileByFlow() = dao.getAlphabetizedWordsByFlow().asLiveData()
    /**
     * 任务开始下载
     */
    private fun startDownloadFile(bean: FileDownloadBean) {
        addTask {
            netThreadPool.execute {
                FileDownloadUtils.getRenewalDownRequest(bean,
                    object : FileDownloadUtils.HttpDownloadListener {
                        override fun onReady(call: Call, bean: FileDownloadBean) {
                            map.put(bean.uuid, call)
                        }

                        override fun onFailure(
                            call: Call,
                            bean: FileDownloadBean,
                            e: IOException?
                        ) {
                            removeTask()
                            upload(bean.apply {
                                this.downloadSpeed = 0
                                this.downloadState = FileDownloadBean.DOWNLOAD_ERROR
                                this.state = "${STATE_NET_FLAG}网络异常，请点击重新下载"
                            })
                        }

                        override fun onResponse(
                            call: Call,
                            response: Response,
                            bean: FileDownloadBean
                        ) {
                            dao.getFileDownloadBeanByUUID(bean.uuid)?.also {
                                upload(bean.apply {
                                    this.downloadState = FileDownloadBean.DOWNLOAD_RUNNING
                                    this.state =
                                        "${STATE_DEFAULT_FLAG}已下载:${(downloadSize.toDouble() / length * 100).toInt()}%"
                                })
                            } ?: let {
                                call.cancel()
                            }
                        }

                        override fun onFinish(bean: FileDownloadBean, e: Exception?) {
                            removeTask()
                            databaseThreadPool.execute {
                                upload(bean.apply {
                                    e?.also {
                                        this.downloadState = FileDownloadBean.DOWNLOAD_ERROR
                                        this.state = "${STATE_NET_FLAG}网络异常，请点击重新下载"
                                    } ?: also {
                                        if (downloadSize == length) {
                                            this.downloadState =
                                                FileDownloadBean.DOWNLOAD_FINISH
                                            this.state = "${STATE_DEFAULT_FLAG}下载到：本地"
                                        }
                                    }
                                    this.downloadSpeed = 0
                                })
                            }
                        }
                    })
            }
        }
    }

    /**
     * 更新所任务
     */
    fun updateAllTaskState() {
        databaseThreadPool.execute {
            dao.updateAllTask()
        }
    }

    private val downloadTaskSize = AtomicInteger(0)

    private fun addTask(run: () -> Unit) {
        // 判断任务是否已满
        val addAndGet = downloadTaskSize.get()
        if (addAndGet >= 2) {
            return
        }
        // 任务标志+1
        downloadTaskSize.getAndIncrement()
        run.invoke()
    }

    private fun currTask(): Int {
        return downloadTaskSize.get()
    }

    private fun removeTask() {
        downloadTaskSize.getAndDecrement()
        if (downloadTaskSize.get() < 0) {
            downloadTaskSize.set(0)
        }
    }

}